package Kuaishou;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;

/**
 * https://javakk.com/225.html
 * @author leiwenkang <leiwenkang@kuaishou.com>
 * Created on 2021-04-20
 */
public class Test39CompletableFuture {

    public static void main(String[] args) throws Exception {
//        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() ->
//                "hello"
//        );
//        // f2依赖f1的结果做转换
//        CompletableFuture<String> f2 = f1.thenApplyAsync(t ->
//                t + " world"
//        );
//        long time = System.currentTimeMillis();
//        System.out.println("异步结果:" + f2.get());
//        System.out.println("耗时:" + (System.currentTimeMillis() - time));


//        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() ->
//                "hello"
//        );
//        // f2虽然依赖f1的结果，但不会等待f1结果返回，而是再包装成一个future返回
//        CompletableFuture<String> f2 = f1.thenComposeAsync(t ->
//                CompletableFuture.supplyAsync(() ->
//                        t + " world"
//                )
//        );
//        // 等到真正调用的时候再执行f2里的逻辑
//        System.out.println("异步结果:" + f2.get());

        //两个异步任务f1、f2是并行执行，彼此无先后依赖顺序
//        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "hello";
//        });
//        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return " world";
//        });
//        CompletableFuture<String> f3 = f1.thenCombineAsync(f2, (t1, t2) ->
//                t1 + t2
//        );
//        long time = System.currentTimeMillis();
//        System.out.println("异步结果:" + f3.get());
//        System.out.println("耗时:" + (System.currentTimeMillis() - time));

        //输出的结果有时候是hello 有时候是world，哪个future先执行完就根据它的结果计算，取两个future最先返回的。
        //如果两个future是同时返回结果，那么applyToEitherAsync永远以第一个future的结果为准
//        Random rand = new Random();
//        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000 + rand.nextInt(1000)); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "hello";
//        });
//        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000 + rand.nextInt(1000)); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "world";
//        });
//        CompletableFuture<String> f3 = f1.applyToEitherAsync(f2, t -> t);
//        long time = System.currentTimeMillis();
//        System.out.println("异步结果:" + f3.get());
//        System.out.println("耗时:" + (System.currentTimeMillis() - time));

        //前面讲的compose,combine,either都是处理两个future的方法，如果是超过2个的可以使用allOf或anyOf
//        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "hello";
//        });
//        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "world";
//        });
//        CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "java老k";
//        });
//        List<CompletableFuture<String>> list = new ArrayList<>();
//        list.add(f1);
//        list.add(f2);
//        list.add(f3);
//
//        CompletableFuture<Void> f4 = CompletableFuture.allOf(list.toArray(new CompletableFuture[]{}));
//        long time = System.currentTimeMillis();
//        f4.thenRunAsync(() ->
//                list.forEach(f -> {
//                    try {
//                        System.out.println("异步结果:" + f.get());
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                })
//        );
//        f4.get();
//        System.out.println("耗时:" + (System.currentTimeMillis() - time));

        //多次执行输出的结果不一样，anyOf方法当任意一个CompletableFuture执行完后就会执行计算。
//        Random rand = new Random(); // 随机数
//        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000 + rand.nextInt(1000)); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "hello";
//        });
//        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000 + rand.nextInt(1000)); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "world";
//        });
//        CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(1000 + rand.nextInt(1000)); // 模拟接口调用耗时1秒
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            return "java老k";
//        });
//
//        CompletableFuture<Object> f4 = CompletableFuture.anyOf(f1, f2, f3);
//        long time = System.currentTimeMillis();
//        System.out.println("异步结果:" + f4.get());
//        System.out.println("耗时:" + (System.currentTimeMillis() - time));


    }
}
